<template>
  <div class="speech-container">
      <!-- 网络状态组件 -->
      <!-- <NetworkStatusComponent /> -->
      
      <!-- 功能选择 -->
      <el-card class="mode-selector">
        <el-radio-group v-model="recognitionMode" @change="onModeChange">
          <el-radio-button label="online">在线语音识别</el-radio-button>
          <el-radio-button label="offline">离线录音</el-radio-button>
          <el-radio-button label="file">文件转文字</el-radio-button>
        </el-radio-group>
      </el-card>
      
      <!-- 在线语音识别 -->
      <el-card v-if="recognitionMode === 'online'" class="speech-card">
        <template #header>
          <div class="card-header">
            <h2>在线语音识别</h2>
            <el-tag :type="isRecording ? 'danger' : 'info'">
              {{ isRecording ? '正在录音' : '准备就绪' }}
            </el-tag>
          </div>
        </template>
        
        <div class="speech-content">
          <!-- 识别设置 -->
          <div class="recognition-settings">
            <el-row :gutter="20">
              <el-col :span="12">
                <el-form-item label="识别语言">
                  <el-select v-model="recognitionLanguage" placeholder="选择语言" @change="updateRecognitionSettings">
                    <el-option label="中文普通话" value="zh" />
                    <el-option label="英语" value="en" />
                  </el-select>
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="识别模型">
                  <el-select v-model="recognitionModel" placeholder="选择模型" @change="updateRecognitionSettings">
                    <el-option label="普通话搜索" :value="1537" />
                    <el-option label="英语" :value="1737" />
                    <el-option label="粤语" :value="1637" />
                  </el-select>
                </el-form-item>
              </el-col>
            </el-row>
          </div>
          
          <!-- 录音控制区域 -->
          <div class="control-section">
            <el-button 
              :type="isRecording ? 'danger' : 'primary'"
              :icon="isRecording ? 'VideoPause' : 'Microphone'"
              size="large"
              @click="toggleRecording"
              :loading="isProcessing"
            >
              {{ isRecording ? '停止录音' : '开始录音' }}
            </el-button>
            
            <el-button 
              v-if="!isOnline"
              type="warning"
              :icon="'Connection'"
              size="large"
              @click="forceStartRecording"
              :loading="isProcessing"
            >
              强制开始录音
            </el-button>
            
            <el-button 
              type="warning"
              icon="Delete"
              size="large"
              @click="clearText"
              :disabled="!recognizedText"
            >
              清空文本
            </el-button>
          </div>
          
          <!-- 状态显示 -->
          <div class="status-section">
            <!-- 网络状态指示器 -->
            <div class="network-status">
              <el-tag :type="isOnline ? 'success' : 'danger'" size="small">
                <el-icon><Connection /></el-icon>
                {{ isOnline ? '网络已连接' : '网络已断开' }}
              </el-tag>
              <span v-if="!isOnline" class="network-warning">
                <el-icon><Warning /></el-icon>
                语音识别需要网络连接
              </span>
              <div v-if="isRecording" class="recording-network-status">
                <el-icon class="network-monitor-icon"><Monitor /></el-icon>
                <span>正在监控网络连接...</span>
              </div>
            </div>
            
            <el-alert
              v-if="errorMessage"
              :title="errorMessage"
              type="error"
              show-icon
              :closable="false"
            >
              <template #default>
                <div class="error-content">
                  <p>{{ errorMessage }}</p>
                  <div class="error-actions">
                    <el-button 
                      v-if="errorMessage.includes('网络')"
                      type="primary" 
                      size="small" 
                      @click="retryRecording"
                    >
                      重试
                    </el-button>
                    <el-button 
                      v-if="errorMessage.includes('网络')"
                      type="info" 
                      size="small" 
                      @click="showNetworkHelp"
                    >
                      网络帮助
                    </el-button>
                  </div>
                </div>
              </template>
            </el-alert>
            
            <el-alert
              v-if="isRecording"
              title="正在录音中，请说话..."
              type="info"
              show-icon
              :closable="false"
            />
            
            <el-alert
              v-if="!isRecording && !errorMessage && !recognizedText"
              title="点击开始录音按钮开始语音识别"
              type="success"
              show-icon
              :closable="false"
            />
          </div>
          
          <!-- 文本显示区域 -->
          <div class="text-section">
            <h3>识别结果：</h3>
            <el-input
              v-model="recognizedText"
              type="textarea"
              :rows="10"
              placeholder="语音识别结果将显示在这里..."
              readonly
              class="result-textarea"
            />
          </div>
          
          <!-- 操作按钮 -->
          <div class="action-section">
            <el-button 
              type="success"
              icon="CopyDocument"
              @click="copyText"
              :disabled="!recognizedText"
            >
              复制文本
            </el-button>
            
            <el-button 
              type="info"
              icon="Download"
              @click="downloadText"
              :disabled="!recognizedText"
            >
              下载文本
            </el-button>
          </div>
        </div>
      </el-card>
      
      <!-- 使用说明 -->
      <el-card class="help-card">
        <template #header>
          <h3>使用说明</h3>
        </template>
        <ul class="help-list">
          <li>点击"开始录音"按钮开始语音识别</li>
          <li>请确保浏览器已授权麦克风权限</li>
          <li>确保网络连接稳定，语音识别需要网络支持</li>
          <li>说话时请保持清晰，避免背景噪音</li>
          <li>点击"停止录音"结束识别过程</li>
          <li>识别结果会自动显示在文本框中</li>
          <li>可以复制或下载识别结果</li>
          <li>如遇到网络错误，请检查网络连接后重试</li>
        </ul>
      </el-card>
      
      <!-- 网络帮助对话框 -->
      <el-dialog
        v-model="networkHelpVisible"
        title="网络问题解决方案"
        width="600px"
      >
        <div class="network-help">
          <h4>语音识别网络错误解决方案：</h4>
          <ol>
            <li><strong>检查网络连接</strong>：确保您的设备已连接到互联网</li>
            <li><strong>检查防火墙设置</strong>：确保浏览器可以访问外部服务</li>
            <li><strong>尝试其他浏览器</strong>：Chrome、Edge、Safari对语音识别支持最好</li>
            <li><strong>检查代理设置</strong>：如果使用代理，确保语音服务未被阻止</li>
            <li><strong>重启浏览器</strong>：有时重启浏览器可以解决连接问题</li>
            <li><strong>检查系统时间</strong>：确保系统时间正确，SSL证书验证需要</li>
            <li><strong>尝试强制录音</strong>：点击"强制开始录音"按钮跳过网络检查</li>
            <li><strong>检查麦克风权限</strong>：确保浏览器有麦克风访问权限</li>
          </ol>
          
          <h4>替代方案：</h4>
          <ul>
            <li>使用手机热点测试网络连接</li>
            <li>尝试在无痕模式下使用</li>
            <li>检查是否有企业网络限制</li>
            <li>尝试使用不同的网络环境</li>
            <li>检查DNS设置是否正确</li>
          </ul>
          
          <h4>常见问题：</h4>
          <ul>
            <li><strong>网络显示连接但无法录音</strong>：可能是DNS问题，尝试更换DNS服务器</li>
            <li><strong>录音开始后立即停止</strong>：检查麦克风是否被其他应用占用</li>
            <li><strong>识别结果为空</strong>：确保说话清晰，环境安静</li>
            <li><strong>ERR_NETWORK_CHANGED错误</strong>：网络状态发生变化，等待几秒后重试或使用强制录音</li>
            <li><strong>网络检查超时</strong>：网络较慢，可以尝试使用强制录音功能</li>
          </ul>
        </div>
        <template #footer>
          <el-button @click="networkHelpVisible = false">关闭</el-button>
          <el-button type="primary" @click="testNetworkConnection">测试网络连接</el-button>
        </template>
      </el-dialog>
      
      <!-- 离线录音功能 -->
      <el-card v-if="recognitionMode === 'offline'" class="speech-card">
        <template #header>
          <div class="card-header">
            <h2>离线录音</h2>
            <el-tag :type="isRecording ? 'danger' : 'success'">
              {{ isRecording ? '正在录音' : '准备就绪' }}
            </el-tag>
          </div>
        </template>
        
        <div class="speech-content">
          <!-- 录音控制区域 -->
          <div class="control-section">
            <el-button 
              :type="isRecording ? 'danger' : 'primary'"
              :icon="isRecording ? 'VideoPause' : 'Microphone'"
              size="large"
              @click="toggleOfflineRecording"
              :loading="isProcessing"
              :disabled="!isOfflineSupported"
            >
              {{ isRecording ? '停止录音' : '开始录音' }}
            </el-button>
            
            <el-button 
              type="warning"
              icon="Delete"
              size="large"
              @click="clearOfflineText"
              :disabled="!offlineText"
            >
              清空文本
            </el-button>
            
            <el-button 
              type="info"
              icon="Download"
              size="large"
              @click="downloadOfflineAudio"
              :disabled="!offlineAudioBlob"
            >
              下载音频
            </el-button>
            
            <el-button
              v-if="offlineAudioBlob && !offlineText"
              type="success"
              icon="Microphone"
              size="large"
              @click="convertAudioToText(offlineAudioBlob)"
              :loading="isProcessing"
            >
              转换为文字
            </el-button>
            
          </div>
          
          <!-- 录音状态显示 -->
          <div class="status-section">
            <div class="recording-info" v-if="isRecording">
              <el-icon class="recording-icon"><Microphone /></el-icon>
              <span>录音时长: {{ formatTime(recordingTime) }}</span>
              <span>文件大小: {{ formatFileSize(audioSize) }}</span>
            </div>
            
            <div class="error-message" v-if="offlineErrorMessage">
              <el-alert
                :title="offlineErrorMessage"
                type="error"
                :closable="false"
                show-icon
              />
            </div>
          </div>
          
          <!-- 识别结果 -->
          <div class="result-section">
            <h3>录音结果：</h3>
            <el-input
              v-model="offlineText"
              type="textarea"
              :rows="6"
              placeholder="录音结果将显示在这里..."
              readonly
              class="result-textarea"
            />
            
            <div class="result-actions" v-if="offlineText">
              <el-button 
                type="primary" 
                icon="CopyDocument"
                @click="copyOfflineText"
              >
                复制文本
              </el-button>
              <el-button 
                type="success" 
                icon="Download"
                @click="downloadOfflineText"
              >
                下载文本
              </el-button>
            </div>
          </div>
          
          <!-- 使用说明 -->
          <div class="help-section">
            <el-collapse>
              <el-collapse-item title="使用说明" name="help">
                <ul class="help-list">
                  <li>点击"开始录音"按钮开始录制音频</li>
                  <li>请确保浏览器已授权麦克风权限</li>
                  <li>点击"停止录音"结束录制</li>
                  <li>录音完成后会自动进行语音识别转换为文字</li>
                  <li>如果自动转换失败，可点击"转换为文字"按钮手动转换</li>
                  <li>录音文件会自动保存，可以下载</li>
                  <li>在线和离线模式都使用百度语音识别API，识别准确度高</li>
                  <li>如果百度API失败，会自动回退到Web Speech API</li>
                  <li>请确保录音清晰，环境安静，以获得更好的识别效果</li>
                  <li><strong>注意：需要配置百度API密钥才能使用</strong></li>
                </ul>
              </el-collapse-item>
            </el-collapse>
          </div>
        </div>
      </el-card>
      
      <!-- 文件转文字功能 -->
      <el-card v-if="recognitionMode === 'file'" class="speech-card">
        <template #header>
          <div class="card-header">
            <h2>文件转文字</h2>
            <el-tag :type="fileProcessing ? 'warning' : 'success'">
              {{ fileProcessing ? '处理中...' : '准备就绪' }}
            </el-tag>
          </div>
        </template>
        
        <div class="speech-content">
          <!-- 文件上传区域 -->
          <div class="upload-section">
            <el-upload
              ref="fileUploadRef"
              class="file-uploader"
              drag
              :auto-upload="false"
              :on-change="handleFileChange"
              :before-upload="beforeFileUpload"
              :accept="'.mp3,.wav,.m4a,.aac,.ogg,.webm,.flac'"
              :limit="1"
              :on-exceed="handleExceed"
            >
              <el-icon class="el-icon--upload"><upload-filled /></el-icon>
              <div class="el-upload__text">
                将音频文件拖到此处，或<em>点击上传</em>
              </div>
              <template #tip>
                <div class="el-upload__tip">
                  支持格式：MP3, WAV, M4A, AAC, OGG, WEBM, FLAC
                </div>
              </template>
            </el-upload>
          </div>
          
          <!-- 文件信息显示 -->
          <div class="file-info" v-if="selectedFile">
            <el-card class="file-details">
              <div class="file-detail-item">
                <span class="label">文件名：</span>
                <span class="value">{{ selectedFile.name }}</span>
              </div>
              <div class="file-detail-item">
                <span class="label">文件大小：</span>
                <span class="value">{{ formatFileSize(selectedFile.size) }}</span>
              </div>
              <div class="file-detail-item">
                <span class="label">文件类型：</span>
                <span class="value">{{ selectedFile.type || '未知' }}</span>
              </div>
            </el-card>
          </div>
          
          <!-- 处理控制 -->
          <div class="control-section" v-if="selectedFile">
            <el-button 
              type="primary"
              icon="Microphone"
              size="large"
              @click="processAudioFile"
              :loading="fileProcessing"
              :disabled="!selectedFile"
            >
              {{ fileProcessing ? '处理中...' : '开始转换' }}
            </el-button>
            
            <el-button 
              type="warning"
              icon="Delete"
              size="large"
              @click="clearFile"
              :disabled="fileProcessing"
            >
              清除文件
            </el-button>
            
            <el-button 
              type="info"
              icon="Download"
              size="large"
              @click="downloadFileText"
              :disabled="!fileText || fileProcessing"
            >
              下载文本
            </el-button>
          </div>
          
          <!-- 处理进度 -->
          <div class="progress-section" v-if="fileProcessing">
            <el-progress 
              :percentage="processingProgress" 
              :status="processingProgress === 100 ? 'success' : undefined"
            />
            <p class="progress-text">{{ processingStatus }}</p>
          </div>
          
          <!-- 错误信息 -->
          <div class="error-message" v-if="fileErrorMessage">
            <el-alert
              :title="fileErrorMessage"
              type="error"
              :closable="false"
              show-icon
            />
          </div>
          
          <!-- 转换结果 -->
          <div class="result-section" v-if="fileText">
            <h3>转换结果：</h3>
            <el-input
              v-model="fileText"
              type="textarea"
              :rows="8"
              placeholder="转换结果将显示在这里..."
              readonly
              class="result-textarea"
            />
            
            <div class="result-actions">
              <el-button 
                type="primary" 
                icon="CopyDocument"
                @click="copyFileText"
              >
                复制文本
              </el-button>
              <el-button 
                type="success" 
                icon="Download"
                @click="downloadFileText"
              >
                下载文本
              </el-button>
            </div>
          </div>
          
          <!-- 使用说明 -->
          <div class="help-section">
            <el-collapse>
              <el-collapse-item title="使用说明" name="help">
                <ul class="help-list">
                  <li>支持上传MP3、WAV、M4A、AAC、OGG、WEBM、FLAC格式的音频文件</li>
                  <li>文件大小建议不超过50MB，时长不超过10分钟</li>
                  <li>上传后点击"开始转换"进行语音识别</li>
                  <li>转换完成后可以复制或下载识别结果</li>
                  <li>此功能需要网络连接，使用在线语音识别服务</li>
                </ul>
              </el-collapse-item>
            </el-collapse>
          </div>
        </div>
      </el-card>
    </div>
  </template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import { ElMessage } from 'element-plus'
import { NetworkDiagnostic } from '@/utils/networkDiagnostic'
import { NetworkManager } from '@/utils/offlineSpeechRecognition'
// import NetworkStatusComponent from '@/components/NetworkStatusComponent.vue'
import { SafeTimer } from '@/utils/safeTimers'
// import { default as OfflineSpeechRecognition } from '@/components/OfflineSpeechRecognition.vue'

// 响应式数据
const isRecording = ref(false)
const isProcessing = ref(false)
const recognizedText = ref('')
const errorMessage = ref('')

// 识别设置
const recognitionLanguage = ref('zh')
const recognitionModel = ref(1537)

// 更新识别设置
const updateRecognitionSettings = () => {
  console.log('更新识别设置:', {
    language: recognitionLanguage.value,
    model: recognitionModel.value
  })
}
const recognition = ref<SpeechRecognition | null>(null)
const networkHelpVisible = ref(false)
const isOnline = ref(true)
const recognitionMode = ref<'online' | 'offline' | 'file'>('online')
// const offlineSpeechRecognition = OfflineSpeechRecognition.getInstance() // 暂时未使用
const networkManager = NetworkManager.getInstance()
const networkMonitorInterval = ref<ReturnType<typeof setInterval> | null>(null)

// 离线录音相关数据
const isOfflineSupported = ref(false)
const offlineText = ref('')
const offlineErrorMessage = ref('')
const offlineAudioBlob = ref<Blob | null>(null)
const recordingTime = ref(0)
const audioSize = ref(0)

// 离线录音相关变量
let offlineRecorder: any = null
let offlineMediaStream: MediaStream | null = null
let offlineRecordingTimer: number | null = null

// 文件转文字相关数据
const fileUploadRef = ref()
const selectedFile = ref<File | null>(null)
const fileProcessing = ref(false)
const fileText = ref('')
const fileErrorMessage = ref('')
const processingProgress = ref(0)
const processingStatus = ref('')

// 检查浏览器支持
const checkBrowserSupport = () => {
  const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition
  if (!SpeechRecognition) {
    errorMessage.value = '您的浏览器不支持语音识别功能，请使用Chrome、Edge或Safari浏览器'
    return false
  }
  
  return true
}

// 检查网络连接状态
const checkNetworkStatus = async () => {
  // 使用网络管理器检查状态
  isOnline.value = networkManager.getOnlineStatus()
  
  if (!isOnline.value) {
    errorMessage.value = '网络连接不可用，语音识别需要网络连接'
    return false
  }
  
  // 使用网络管理器的测试连接功能
  try {
    const connected = await networkManager.testConnection(2, 3000) // 2次重试，3秒超时
    isOnline.value = connected
    
    if (!connected) {
      // 检查是否是网络状态变化导致的失败
      if (navigator.onLine) {
        errorMessage.value = '网络状态不稳定，建议稍后重试或使用强制录音'
        return false
      } else {
        errorMessage.value = '网络连接已断开，请检查网络设置'
        return false
      }
    }
    
    return true
  } catch (error: any) {
    console.error('网络检查异常:', error)
    isOnline.value = false
    
    // 根据错误类型提供不同的提示
    if (error.message?.includes('ERR_NETWORK_CHANGED')) {
      errorMessage.value = '网络状态发生变化，请稍后重试或使用强制录音'
    } else if (error.message?.includes('ERR_INTERNET_DISCONNECTED')) {
      errorMessage.value = '网络连接已断开，请检查网络设置'
    } else {
      errorMessage.value = '网络连接测试失败，请检查网络设置'
    }
    return false
  }
}

// 初始化语音识别
// 在线录音相关变量
const onlineMediaRecorder = ref<MediaRecorder | null>(null)
const onlineMediaStream = ref<MediaStream | null>(null)
const onlineAudioChunks = ref<Blob[]>([])

// 初始化在线语音识别（使用百度API）
const initSpeechRecognition = () => {
  if (!checkBrowserSupport()) return
  
  // 检查百度API配置
  if (!isBaiduAPIConfigured()) {
    errorMessage.value = '百度API未配置，请先配置API密钥'
    ElMessage.error('百度API未配置，请先配置API密钥')
    return
  }
  
  // 使用Web Speech API作为备用方案
  const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition
  if (SpeechRecognition) {
    recognition.value = new SpeechRecognition()
    
    // 配置识别参数
    recognition.value.continuous = true
    recognition.value.interimResults = true
    recognition.value.lang = 'zh-CN'
    
    // 识别开始
    recognition.value.onstart = () => {
      isRecording.value = true
      isProcessing.value = false
      errorMessage.value = ''
      ElMessage.success('开始录音')
      startNetworkMonitoring() // 开始网络监控
    }
    
    // 识别结果
    recognition.value.onresult = (event: SpeechRecognitionEvent) => {
      let finalTranscript = ''
      let interimTranscript = ''
      
      for (let i = event.resultIndex; i < event.results.length; i++) {
        const transcript = event.results[i][0].transcript
        if (event.results[i].isFinal) {
          finalTranscript += transcript
        } else {
          interimTranscript += transcript
        }
      }
      
      recognizedText.value = finalTranscript + interimTranscript
    }
    
    // 识别结束
    recognition.value.onend = () => {
      isRecording.value = false
      isProcessing.value = false
      ElMessage.info('录音结束')
      stopNetworkMonitoring() // 停止网络监控
    }
    
    // 识别错误
    recognition.value.onerror = (event: SpeechRecognitionErrorEvent) => {
      isRecording.value = false
      isProcessing.value = false
      stopNetworkMonitoring() // 停止网络监控
      
      let errorMsg = ''
      switch (event.error) {
        case 'network':
          errorMsg = '网络错误：请检查网络连接，语音识别需要稳定的网络连接'
          break
        case 'not-allowed':
          errorMsg = '权限错误：请允许麦克风权限'
          break
        case 'no-speech':
          errorMsg = '未检测到语音：请确保麦克风正常工作并说话'
          break
        case 'aborted':
          errorMsg = '识别被中断：请重试'
          break
        case 'audio-capture':
          errorMsg = '音频捕获错误：请检查麦克风设备'
          break
        case 'service-not-allowed':
          errorMsg = '服务不允许：语音识别服务不可用'
          break
        default:
          errorMsg = `识别错误: ${event.error}`
      }
      
      errorMessage.value = errorMsg
      ElMessage.error(errorMsg)
    }
  }
}

// 录音前网络预检查
const preRecordingNetworkCheck = async () => {
  // 首先检查基本的在线状态
  if (!navigator.onLine) {
    ElMessage.error('网络连接已断开，请检查网络设置')
    errorMessage.value = '网络连接已断开，请检查网络设置'
    return false
  }
  
  ElMessage.info('正在检查网络连接...')
  
  try {
    // 使用更宽松的网络检查策略，减少重试次数和超时时间
    const connected = await networkManager.testConnection(1, 1500) // 1次重试，1.5秒超时
    
    if (connected) {
      ElMessage.success('网络连接正常，可以开始录音')
      return true
    } else {
      // 如果网络检查失败，但浏览器显示在线，仍然允许尝试
      ElMessage.warning('网络连接不稳定，但可以尝试录音')
      return true // 改为返回true，允许尝试录音
    }
  } catch (error: any) {
    console.error('网络检查异常:', error)
    
    // 如果检查过程出错，但浏览器显示在线，仍然允许尝试
    if (navigator.onLine) {
      ElMessage.info('网络检查异常，但基本连接可用，可以尝试录音')
      return true
    } else {
      ElMessage.error('网络连接不可用，请检查网络设置')
      errorMessage.value = '网络连接不可用，请检查网络设置'
      return false
    }
  }
}

// 强制开始录音（跳过网络检查）
const forceStartRecording = async () => {
  if (!recognition.value) {
    ElMessage.error('语音识别未初始化')
    return
  }
  
  if (isRecording.value) {
    ElMessage.warning('已经在录音中')
    return
  }
  
  if (isProcessing.value) return
  
  isProcessing.value = true
  errorMessage.value = ''
  
  ElMessage.warning('跳过网络检查，强制开始录音...')
  
  try {
    recognition.value.start()
  } catch (error) {
    console.error('强制录音失败:', error)
    ElMessage.error('强制录音失败，请检查麦克风权限')
    errorMessage.value = '强制录音失败，请检查麦克风权限'
    isProcessing.value = false
  }
}

// 切换录音状态
// 开始在线录音（使用百度API）
const startOnlineRecording = async () => {
  try {
    // 检查百度API配置
    if (!isBaiduAPIConfigured()) {
      ElMessage.error('百度API未配置，请先配置API密钥')
      return
    }
    
    // 获取麦克风权限
    onlineMediaStream.value = await navigator.mediaDevices.getUserMedia({
      audio: {
        echoCancellation: true,
        noiseSuppression: true,
        autoGainControl: true
      }
    })
    
    // 创建MediaRecorder
    onlineMediaRecorder.value = new MediaRecorder(onlineMediaStream.value, {
      mimeType: 'audio/webm;codecs=opus'
    })
    
    // 重置音频块
    onlineAudioChunks.value = []
    
    // 监听数据可用事件
    onlineMediaRecorder.value.ondataavailable = (event) => {
      if (event.data.size > 0) {
        onlineAudioChunks.value.push(event.data)
      }
    }
    
    // 监听录音结束事件
    onlineMediaRecorder.value.onstop = async () => {
      // 合并音频块
      const audioBlob = new Blob(onlineAudioChunks.value, { type: 'audio/webm' })
      
      // 使用百度API进行识别
      try {
        isProcessing.value = true
        recognizedText.value = '正在识别语音...'
        
        await recognizeWithBaiduAPI(audioBlob)
        
        // 将识别结果添加到现有文本
        if (recognizedText.value && !recognizedText.value.includes('正在识别语音...')) {
          // 识别成功，文本已经在recognizeWithBaiduAPI中设置
        }
        
      } catch (error: any) {
        console.error('百度API识别失败:', error)
        recognizedText.value = `识别失败: ${error.message}`
        ElMessage.error('语音识别失败')
      } finally {
        isProcessing.value = false
      }
    }
    
    // 开始录音
    onlineMediaRecorder.value.start(1000) // 每秒收集一次数据
    isRecording.value = true
    ElMessage.success('开始录音')
    
  } catch (error: any) {
    console.error('开始录音失败:', error)
    ElMessage.error(`开始录音失败: ${error.message}`)
  }
}

// 停止在线录音
const stopOnlineRecording = () => {
  if (onlineMediaRecorder.value && isRecording.value) {
    onlineMediaRecorder.value.stop()
    isRecording.value = false
    ElMessage.info('录音结束')
    
    // 停止媒体流
    if (onlineMediaStream.value) {
      onlineMediaStream.value.getTracks().forEach(track => track.stop())
      onlineMediaStream.value = null
    }
  }
}

const toggleRecording = async () => {
  if (isRecording.value) {
    stopOnlineRecording()
  } else {
    // 清除之前的错误信息
    errorMessage.value = ''
    
    // 录音前网络预检查
    const networkOk = await preRecordingNetworkCheck()
    if (!networkOk) {
      return
    }
    
    // 再次检查网络状态
    const finalCheck = await checkNetworkStatus()
    if (!finalCheck) {
      return
    }
    
    // 使用新的在线录音功能
    await startOnlineRecording()
  }
}

// 重试录音
const retryRecording = async () => {
  errorMessage.value = ''
  
  // 先检查网络
  const networkOk = await checkNetworkStatus()
  if (!networkOk) {
    return
  }
  
  if (recognition.value) {
    try {
      recognition.value.start()
    } catch (error) {
      errorMessage.value = '启动语音识别失败，请重试'
    }
  } else {
    // 重新初始化
    initSpeechRecognition()
    const retryTimer = SafeTimer.setTimeout(async () => {
      if (recognition.value) {
        try {
          recognition.value.start()
        } catch (error) {
          errorMessage.value = '启动语音识别失败，请重试'
        }
      }
    }, 100)
    
    // 清理定时器
    if (!recognition.value) {
      SafeTimer.clearTimeout(retryTimer)
    }
  }
}

// 显示网络帮助
const showNetworkHelp = () => {
  networkHelpVisible.value = true
}

// 测试网络连接
const testNetworkConnection = async () => {
  ElMessage.info('正在运行网络诊断...')
  
  try {
    // 设置超时保护
    const timeoutPromise = new Promise((_, reject) => {
      const timeoutTimer = SafeTimer.setTimeout(() => reject(new Error('诊断超时')), 10000) // 10秒总超时
      // 清理定时器
      return () => SafeTimer.clearTimeout(timeoutTimer)
    })
    
    const diagnosticPromise = NetworkDiagnostic.runDiagnostic()
    const result = await Promise.race([diagnosticPromise, timeoutPromise]) as any
    
    const recommendations = NetworkDiagnostic.getRecommendations(result)
    const browserSupport = NetworkDiagnostic.getBrowserSupport()
    
    let message = `网络诊断完成：\n`
    message += `• 网络状态: ${result.isOnline ? '已连接' : '已断开'}\n`
    message += `• Google服务: ${result.canReachGoogle ? '可访问' : '无法访问'}\n`
    message += `• 语音服务: ${result.canReachSpeechService ? '可访问' : '无法访问'}\n`
    message += `• 浏览器: ${browserSupport.browser} ${browserSupport.version || ''}\n`
    message += `• 支持状态: ${browserSupport.supported ? '支持' : '不支持'}\n\n`
    message += `建议：\n${recommendations.join('\n')}`
    
    ElMessage({
      message: message,
      type: result.isOnline && result.canReachGoogle ? 'success' : 'warning',
      duration: 10000,
      showClose: true
    })
    
    if (result.isOnline && result.canReachGoogle && browserSupport.supported) {
      networkHelpVisible.value = false
    }
  } catch (error) {
    console.error('网络诊断错误:', error)
    ElMessage.error('网络诊断失败，可能是网络连接问题或超时')
  }
}

// 清空文本
const clearText = () => {
  recognizedText.value = ''
  ElMessage.success('文本已清空')
}

// 复制文本
const copyText = async () => {
  try {
    await navigator.clipboard.writeText(recognizedText.value)
    ElMessage.success('文本已复制到剪贴板')
  } catch (err) {
    ElMessage.error('复制失败，请手动选择文本复制')
  }
}

// 下载文本
const downloadText = () => {
  const blob = new Blob([recognizedText.value], { type: 'text/plain;charset=utf-8' })
  const url = URL.createObjectURL(blob)
  const link = document.createElement('a')
  link.href = url
  link.download = `语音识别结果_${new Date().toLocaleString()}.txt`
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
  URL.revokeObjectURL(url)
  ElMessage.success('文本已下载')
}

// 更新网络状态
const updateNetworkStatus = (online: boolean) => {
  isOnline.value = online
}

// 开始网络监控
const startNetworkMonitoring = () => {
  if (networkMonitorInterval.value) {
    SafeTimer.clearInterval(networkMonitorInterval.value)
  }
  
  networkMonitorInterval.value = SafeTimer.setInterval(async () => {
    if (isRecording.value) {
      // 首先检查基本的在线状态，避免频繁的网络请求
      if (!navigator.onLine) {
        ElMessage.warning('网络连接已断开')
        isOnline.value = false
        if (recognition.value && isRecording.value) {
          recognition.value.stop()
        }
        return
      }
      
      // 减少网络检查频率，只在必要时进行
      const connected = await networkManager.testConnection(1, 1500)
      if (!connected) {
        ElMessage.warning('网络连接不稳定，建议使用强制录音')
        isOnline.value = false
        
        // 不自动停止录音，让用户选择
        // 如果用户想继续，可以使用强制录音功能
      } else {
        isOnline.value = true
      }
    }
  }, 10000) // 每10秒检查一次，减少频率
}

// 停止网络监控
const stopNetworkMonitoring = () => {
  if (networkMonitorInterval.value) {
    SafeTimer.clearInterval(networkMonitorInterval.value)
    networkMonitorInterval.value = null
  }
}

// 组件挂载时初始化
// 加载RecordRTC库
const loadRecordRTC = () => {
  return new Promise((resolve, reject) => {
    if (typeof (window as any).RecordRTC !== 'undefined') {
      resolve(true)
      return
    }
    
    // 尝试多个CDN源
    const cdnUrls = [
      'https://cdn.jsdelivr.net/npm/recordrtc@5.6.2/RecordRTC.min.js',
      'https://cdnjs.cloudflare.com/ajax/libs/RecordRTC/5.6.2/RecordRTC.min.js',
      'https://unpkg.com/recordrtc@5.6.2/RecordRTC.min.js'
    ]
    
    let currentIndex = 0
    
    const tryLoadScript = () => {
      if (currentIndex >= cdnUrls.length) {
        reject(new Error('所有CDN源都无法加载RecordRTC库，请检查网络连接'))
        return
      }
      
      const script = document.createElement('script')
      script.src = cdnUrls[currentIndex]
      script.onload = () => {
        console.log(`RecordRTC库从 ${cdnUrls[currentIndex]} 加载成功`)
        resolve(true)
      }
      script.onerror = () => {
        console.warn(`RecordRTC库从 ${cdnUrls[currentIndex]} 加载失败，尝试下一个源`)
        currentIndex++
        tryLoadScript()
      }
      
      // 设置超时
      setTimeout(() => {
        if (typeof (window as any).RecordRTC === 'undefined') {
          console.warn(`RecordRTC库从 ${cdnUrls[currentIndex]} 加载超时，尝试下一个源`)
          script.remove()
          currentIndex++
          tryLoadScript()
        }
      }, 5000) // 5秒超时
      
      document.head.appendChild(script)
    }
    
    tryLoadScript()
  })
}

// 检查离线录音支持
const checkOfflineSupport = async () => {
  const hasGetUserMedia = !!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia)
  
  if (!hasGetUserMedia) {
    offlineErrorMessage.value = '当前浏览器不支持麦克风访问，请使用Chrome、Firefox或Safari浏览器'
    isOfflineSupported.value = false
    return false
  }
  
  try {
    // 尝试加载RecordRTC，但不强制要求
    try {
      await loadRecordRTC()
    } catch (error) {
      console.warn('RecordRTC加载失败，将使用原生MediaRecorder:', error)
    }
    
    const hasRecordRTC = typeof (window as any).RecordRTC !== 'undefined'
    const hasMediaRecorder = typeof MediaRecorder !== 'undefined'
    
    // 只要支持MediaRecorder就可以录音
    const canRecord = hasRecordRTC || hasMediaRecorder
    isOfflineSupported.value = canRecord
    
    if (!canRecord) {
      offlineErrorMessage.value = '当前浏览器不支持录音功能，请使用Chrome、Firefox或Safari浏览器'
    } else if (!hasRecordRTC) {
      offlineErrorMessage.value = 'RecordRTC库加载失败，将使用原生录音功能（功能可能受限）'
    }
    
    return canRecord
  } catch (error) {
    console.error('检查离线录音支持失败:', error)
    offlineErrorMessage.value = '录音功能检查失败，请刷新页面重试'
    isOfflineSupported.value = false
    return false
  }
}

// 初始化离线录音器
const initOfflineRecorder = async () => {
  try {
    offlineMediaStream = await navigator.mediaDevices.getUserMedia({
      audio: {
        echoCancellation: true,
        noiseSuppression: true,
        autoGainControl: true
      }
    })
    
    // 优先使用RecordRTC，如果不可用则使用原生MediaRecorder
    const RecordRTC = (window as any).RecordRTC
    if (RecordRTC) {
      // 检查浏览器支持的音频格式
      let mimeType = 'audio/wav'
      if (!MediaRecorder.isTypeSupported('audio/wav')) {
        if (MediaRecorder.isTypeSupported('audio/webm;codecs=opus')) {
          mimeType = 'audio/webm;codecs=opus'
        } else if (MediaRecorder.isTypeSupported('audio/mp4')) {
          mimeType = 'audio/mp4'
        } else if (MediaRecorder.isTypeSupported('audio/ogg;codecs=opus')) {
          mimeType = 'audio/ogg;codecs=opus'
        }
      }
      
      offlineRecorder = new RecordRTC(offlineMediaStream, {
        type: 'audio',
        mimeType: mimeType,
        sampleRate: 16000, // 使用百度API推荐的采样率
        numberOfAudioChannels: 1,
        timeSlice: 100,
        ondataavailable: (blob: Blob) => {
          audioSize.value = blob.size
        }
      })
      console.log(`使用RecordRTC初始化录音器成功，格式: ${mimeType}`)
    } else {
      // 使用原生MediaRecorder作为备用方案
      let mimeType = 'audio/webm;codecs=opus'
      if (!MediaRecorder.isTypeSupported(mimeType)) {
        if (MediaRecorder.isTypeSupported('audio/mp4')) {
          mimeType = 'audio/mp4'
        } else if (MediaRecorder.isTypeSupported('audio/ogg;codecs=opus')) {
          mimeType = 'audio/ogg;codecs=opus'
        }
      }
      
      offlineRecorder = new MediaRecorder(offlineMediaStream, {
        mimeType: mimeType
      })
      console.log(`使用原生MediaRecorder初始化录音器成功，格式: ${mimeType}`)
    }
    
    return true
  } catch (error: any) {
    console.error('初始化离线录音器失败:', error)
    offlineErrorMessage.value = `初始化录音器失败: ${error.message}`
    return false
  }
}

// 开始离线录音
const startOfflineRecording = async () => {
  if (!offlineRecorder) {
    const success = await initOfflineRecorder()
    if (!success) return
  }
  
  try {
    // 兼容RecordRTC和原生MediaRecorder
    if (typeof (offlineRecorder as any).startRecording === 'function') {
      // RecordRTC
      (offlineRecorder as any).startRecording()
    } else if (typeof (offlineRecorder as any).start === 'function') {
      // 原生MediaRecorder
      (offlineRecorder as any).start()
    }
    
    isRecording.value = true
    recordingTime.value = 0
    audioSize.value = 0
    
    // 开始计时
    offlineRecordingTimer = window.setInterval(() => {
      recordingTime.value++
    }, 1000)
    
    ElMessage.success('开始录音')
  } catch (error: any) {
    console.error('开始录音失败:', error)
    offlineErrorMessage.value = `开始录音失败: ${error.message}`
    ElMessage.error('开始录音失败')
  }
}

// 停止离线录音
const stopOfflineRecording = async () => {
  if (!offlineRecorder) return
  
  try {
    // 兼容RecordRTC和原生MediaRecorder
    if (typeof (offlineRecorder as any).stopRecording === 'function') {
      // RecordRTC
      (offlineRecorder as any).stopRecording(async () => {
        const blob: Blob = (offlineRecorder as any).getBlob()
        offlineAudioBlob.value = blob
        audioSize.value = blob.size
        
        ElMessage.success('录音完成，正在转换为文字...')
        
        // 自动进行语音识别
        await convertAudioToText(blob)
      })
    } else if (typeof (offlineRecorder as any).stop === 'function') {
      // 原生MediaRecorder
      (offlineRecorder as any).stop()
      
      // 监听dataavailable事件获取录音数据
      (offlineRecorder as any).addEventListener('dataavailable', async (event: any) => {
        if (event.data.size > 0) {
          const blob: Blob = event.data
          offlineAudioBlob.value = blob
          audioSize.value = blob.size
          
          ElMessage.success('录音完成，正在转换为文字...')
          
          // 自动进行语音识别
          await convertAudioToText(blob)
        }
      })
    }
    
    isRecording.value = false
    
    // 停止计时
    if (offlineRecordingTimer) {
      clearInterval(offlineRecordingTimer)
      offlineRecordingTimer = null
    }
    
  } catch (error: any) {
    console.error('停止录音失败:', error)
    offlineErrorMessage.value = `停止录音失败: ${error.message}`
    ElMessage.error('停止录音失败')
  }
}

// 切换离线录音状态
const toggleOfflineRecording = async () => {
  if (isProcessing.value) return
  
  isProcessing.value = true
  offlineErrorMessage.value = ''
  
  try {
    if (isRecording.value) {
      await stopOfflineRecording()
    } else {
      await startOfflineRecording()
    }
  } finally {
    isProcessing.value = false
  }
}

// 清空离线文本
const clearOfflineText = () => {
  offlineText.value = ''
  offlineAudioBlob.value = null
  audioSize.value = 0
  recordingTime.value = 0
  ElMessage.info('已清空')
}

// 复制离线文本
const copyOfflineText = async () => {
  try {
    await navigator.clipboard.writeText(offlineText.value)
    ElMessage.success('文本已复制到剪贴板')
  } catch (error) {
    ElMessage.error('复制失败')
  }
}

// 下载离线文本
const downloadOfflineText = () => {
  const blob = new Blob([offlineText.value], { type: 'text/plain' })
  const url = URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = `录音文本_${new Date().toISOString().slice(0, 19).replace(/:/g, '-')}.txt`
  document.body.appendChild(a)
  a.click()
  document.body.removeChild(a)
  URL.revokeObjectURL(url)
  ElMessage.success('文本已下载')
}

// 下载离线音频
const downloadOfflineAudio = () => {
  if (!offlineAudioBlob.value) return
  
  const url = URL.createObjectURL(offlineAudioBlob.value)
  const a = document.createElement('a')
  a.href = url
  a.download = `录音_${new Date().toISOString().slice(0, 19).replace(/:/g, '-')}.wav`
  document.body.appendChild(a)
  a.click()
  document.body.removeChild(a)
  URL.revokeObjectURL(url)
  ElMessage.success('音频已下载')
}

// 格式化时间
const formatTime = (seconds: number) => {
  const mins = Math.floor(seconds / 60)
  const secs = seconds % 60
  return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`
}

// 格式化文件大小
const formatFileSize = (bytes: number) => {
  if (bytes === 0) return '0 B'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}


// 导入百度API配置
import { BAIDU_API_CONFIG, isBaiduAPIConfigured } from '@/config/baidu-api'
import { fetchWithProxy } from '@/config/proxy-config'

// 强制刷新代理配置
console.log('🔄 重新加载代理配置...')

// WebM转WAV格式转换函数
const convertWebmToWav = async (webmBlob: Blob): Promise<Blob> => {
  return new Promise((resolve, reject) => {
    try {
      const audioContext = new (window.AudioContext || (window as any).webkitAudioContext)()
      const fileReader = new FileReader()
      
      fileReader.onload = async () => {
        try {
          const arrayBuffer = fileReader.result as ArrayBuffer
          const audioBuffer = await audioContext.decodeAudioData(arrayBuffer)
          
          // 转换为WAV格式
          const wavBlob = audioBufferToWav(audioBuffer)
          resolve(wavBlob)
        } catch (error) {
          reject(error)
        }
      }
      
      fileReader.onerror = () => reject(new Error('文件读取失败'))
      fileReader.readAsArrayBuffer(webmBlob)
    } catch (error) {
      reject(error)
    }
  })
}

// 将AudioBuffer转换为WAV格式的Blob
const audioBufferToWav = (audioBuffer: AudioBuffer): Blob => {
  const numberOfChannels = audioBuffer.numberOfChannels
  let sampleRate = audioBuffer.sampleRate
  let length = audioBuffer.length
  
  // 如果采样率不是16kHz，需要重采样
  if (sampleRate !== 16000) {
    console.log(`原始采样率: ${sampleRate}Hz，重采样到16000Hz`)
    const resampledBuffer = resampleAudioBuffer(audioBuffer, 16000)
    sampleRate = resampledBuffer.sampleRate
    length = resampledBuffer.length
    audioBuffer = resampledBuffer
  }
  const arrayBuffer = new ArrayBuffer(44 + length * numberOfChannels * 2)
  const view = new DataView(arrayBuffer)
  
  // WAV文件头
  const writeString = (offset: number, string: string) => {
    for (let i = 0; i < string.length; i++) {
      view.setUint8(offset + i, string.charCodeAt(i))
    }
  }
  
  writeString(0, 'RIFF')
  view.setUint32(4, 36 + length * numberOfChannels * 2, true)
  writeString(8, 'WAVE')
  writeString(12, 'fmt ')
  view.setUint32(16, 16, true)
  view.setUint16(20, 1, true)
  view.setUint16(22, numberOfChannels, true)
  view.setUint32(24, sampleRate, true)
  view.setUint32(28, sampleRate * numberOfChannels * 2, true)
  view.setUint16(32, numberOfChannels * 2, true)
  view.setUint16(34, 16, true)
  writeString(36, 'data')
  view.setUint32(40, length * numberOfChannels * 2, true)
  
  // 写入音频数据
  let offset = 44
  for (let i = 0; i < length; i++) {
    for (let channel = 0; channel < numberOfChannels; channel++) {
      const sample = Math.max(-1, Math.min(1, audioBuffer.getChannelData(channel)[i]))
      view.setInt16(offset, sample < 0 ? sample * 0x8000 : sample * 0x7FFF, true)
      offset += 2
    }
  }
  
  return new Blob([arrayBuffer], { type: 'audio/wav' })
}

// 简单的音频重采样函数
const resampleAudioBuffer = (audioBuffer: AudioBuffer, targetSampleRate: number): AudioBuffer => {
  const sourceSampleRate = audioBuffer.sampleRate
  const ratio = sourceSampleRate / targetSampleRate
  const newLength = Math.floor(audioBuffer.length / ratio)
  
  // 创建新的AudioBuffer
  const newBuffer = new AudioBuffer({
    numberOfChannels: audioBuffer.numberOfChannels,
    length: newLength,
    sampleRate: targetSampleRate
  })
  
  // 简单的线性插值重采样
  for (let channel = 0; channel < audioBuffer.numberOfChannels; channel++) {
    const sourceData = audioBuffer.getChannelData(channel)
    const targetData = newBuffer.getChannelData(channel)
    
    for (let i = 0; i < newLength; i++) {
      const sourceIndex = i * ratio
      const index = Math.floor(sourceIndex)
      const fraction = sourceIndex - index
      
      if (index + 1 < sourceData.length) {
        // 线性插值
        targetData[i] = sourceData[index] * (1 - fraction) + sourceData[index + 1] * fraction
      } else {
        targetData[i] = sourceData[index] || 0
      }
    }
  }
  
  return newBuffer
}

// 获取百度API访问令牌（使用代理服务器）
const getBaiduAccessToken = async () => {
  try {
    console.log('开始获取百度API访问令牌...')
    console.log('API Key:', BAIDU_API_CONFIG.API_KEY)
    console.log('Secret Key:', BAIDU_API_CONFIG.SECRET_KEY ? '已配置' : '未配置')
    
    const response = await fetchWithProxy(BAIDU_API_CONFIG.ACCESS_TOKEN_URL, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
      },
      body: new URLSearchParams({
        grant_type: 'client_credentials',
        client_id: BAIDU_API_CONFIG.API_KEY,
        client_secret: BAIDU_API_CONFIG.SECRET_KEY
      })
    })
    
    console.log('百度API响应状态:', response.status)
    console.log('百度API响应头:', response.headers)
    
    const data = await response.json()
    console.log('百度API响应数据:', data)
    
    if (data.access_token) {
      console.log('成功获取访问令牌')
      return data.access_token
    } else if (data.error) {
      console.error('百度API错误详情:', data)
      throw new Error(`百度API错误: ${data.error} - ${data.error_description || ''}`)
    } else {
      console.error('获取访问令牌失败，响应数据:', data)
      throw new Error(`获取访问令牌失败: ${JSON.stringify(data)}`)
    }
  } catch (error) {
    console.error('获取百度API访问令牌失败:', error)
    throw error
  }
}

// 使用百度API进行语音识别
const recognizeWithBaiduAPI = async (audioBlob: Blob) => {
  try {
    // 检查API配置
    if (!isBaiduAPIConfigured()) {
      throw new Error('百度API未配置，请先配置API密钥')
    }
    
    console.log('开始百度API语音识别...')
    console.log('音频文件大小:', audioBlob.size, 'bytes')
    console.log('音频文件类型:', audioBlob.type)
    
    // 检查音频文件大小
    if (audioBlob.size < 1000) {
      throw new Error('音频文件太小，可能没有录制到有效内容')
    }
    
    // 检查音频时长（通过文件大小估算）
    const estimatedDuration = audioBlob.size / 16000 // 粗略估算
    console.log('估算音频时长:', estimatedDuration, '秒')
    
    if (estimatedDuration < 0.5) {
      throw new Error('音频时长太短，请录制至少0.5秒的语音')
    }
    
    offlineText.value = '正在连接百度语音识别服务...'
    
    // 获取访问令牌
    const accessToken = await getBaiduAccessToken()
    
    offlineText.value = '正在处理音频格式...'
    
    // 百度API主要支持pcm和wav格式，需要转换webm格式
    let audioFormat = 'wav'
    let processedAudioBlob = audioBlob
    
    console.log('开始音频格式处理...')
    console.log('音频类型检查:', audioBlob.type)
    
    if (audioBlob.type.includes('webm') || audioBlob.type.includes('WebM')) {
      console.log('检测到webm格式，需要转换为wav格式')
      try {
        // 尝试转换webm为wav格式
        processedAudioBlob = await convertWebmToWav(audioBlob)
        audioFormat = 'wav'
        console.log('webm转换成功，使用wav格式')
      } catch (error) {
        console.warn('webm转换失败，尝试使用原始格式:', error)
        audioFormat = 'pcm' // 百度API也支持pcm格式
      }
    } else if (audioBlob.type.includes('wav') || audioBlob.type.includes('WAV')) {
      audioFormat = 'wav'
      console.log('检测到wav格式，直接使用')
    } else {
      audioFormat = 'pcm' // 默认使用pcm格式
      console.log('使用默认pcm格式')
    }
    
    console.log('检测到的音频格式:', audioBlob.type, '使用格式:', audioFormat)
    
    offlineText.value = '正在上传音频文件...'
    
    // 将处理后的音频Blob转换为Base64
    const arrayBuffer = await processedAudioBlob.arrayBuffer()
    const uint8Array = new Uint8Array(arrayBuffer)
    
    // 使用更安全的方式转换Base64，避免栈溢出
    let binaryString = ''
    const chunkSize = 8192 // 分块处理，避免栈溢出
    
    for (let i = 0; i < uint8Array.length; i += chunkSize) {
      const chunk = uint8Array.slice(i, i + chunkSize)
      binaryString += String.fromCharCode.apply(null, chunk)
    }
    
    const base64Audio = btoa(binaryString)
    
    console.log('音频base64长度:', base64Audio.length)
    
    offlineText.value = '正在进行语音识别...'
    
    // 调用百度语音识别API（使用代理）
    const targetUrl = BAIDU_API_CONFIG.SPEECH_URL
    
    const requestBody = {
      format: audioFormat,
      rate: BAIDU_API_CONFIG.SAMPLE_RATE,
      channel: BAIDU_API_CONFIG.CHANNELS,
      cuid: BAIDU_API_CONFIG.CUID,
      token: accessToken,
      speech: base64Audio,
      len: arrayBuffer.byteLength,
      // 使用用户选择的语言和识别模型参数
      lan: recognitionLanguage.value,
      dev_pid: recognitionModel.value
    }
    
    console.log('发送语音识别请求...')
    console.log('请求URL:', targetUrl)
    console.log('请求体大小:', JSON.stringify(requestBody).length)
    
    const response = await fetchWithProxy(targetUrl, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(requestBody)
    })
    
    console.log('语音识别响应状态:', response.status)
    const result = await response.json()
    console.log('语音识别响应数据:', result)
    console.log('错误码:', result.err_no)
    console.log('错误信息:', result.err_msg)
    console.log('识别结果:', result.result)
    console.log('结果类型:', typeof result.result)
    console.log('结果长度:', result.result ? result.result.length : 'null')
    
    if (result.err_no === 0) {
      if (result.result && result.result.length > 0) {
        // 识别成功
        const recognizedTextResult = result.result.join('')
        console.log('最终识别文本:', recognizedTextResult)
        
        // 根据调用上下文设置正确的变量
        if (recognitionMode.value === 'online') {
          recognizedText.value = recognizedTextResult
        } else {
          offlineText.value = recognizedTextResult
        }
        
        ElMessage.success('语音识别完成')
        return recognizedTextResult
      } else {
        // 识别成功但没有结果
        console.log('识别成功但没有结果，可能是静音或无法识别')
        const noResultMessage = '识别完成，但没有检测到有效语音内容'
        
        // 根据调用上下文设置正确的变量
        if (recognitionMode.value === 'online') {
          recognizedText.value = noResultMessage
        } else {
          offlineText.value = noResultMessage
        }
        
        ElMessage.warning('没有检测到有效语音内容')
        return noResultMessage
      }
    } else {
      // 识别失败
      console.log('百度API返回错误:', result.err_no, result.err_msg)
      throw new Error(`识别失败: ${result.err_msg || '未知错误'} (错误码: ${result.err_no})`)
    }
    
  } catch (error: any) {
    console.error('百度API识别失败:', error)
    throw error
  }
}

// 音频转文字功能
const convertAudioToText = async (audioBlob: Blob) => {
  try {
    // 显示处理状态
    isProcessing.value = true
    offlineErrorMessage.value = ''
    
    // 创建音频URL
    const audioUrl = URL.createObjectURL(audioBlob)
    
    // 创建音频元素
    const audio = new Audio(audioUrl)
    
    // 等待音频加载
    await new Promise((resolve, reject) => {
      audio.onloadedmetadata = resolve
      audio.onerror = reject
    })
    
    const duration = audio.duration
    
    // 清理音频URL
    URL.revokeObjectURL(audioUrl)
    
    // 首先尝试使用百度API
    try {
      await recognizeWithBaiduAPI(audioBlob)
    } catch (baiduError) {
      console.warn('百度API识别失败，尝试Web Speech API:', baiduError)
      
      // 如果百度API失败，回退到Web Speech API
      await recognizeWithWebSpeechAPI(audioBlob, duration)
    }
    
  } catch (error: any) {
    console.error('音频转文字失败:', error)
    offlineErrorMessage.value = `语音识别失败: ${error.message}`
    offlineText.value = '语音识别失败，请重试'
    ElMessage.error('语音识别失败')
    isProcessing.value = false
  }
}

// 使用Web Speech API进行语音识别（备用方案）
const recognizeWithWebSpeechAPI = async (_audioBlob: Blob, duration: number) => {
  return new Promise<void>((resolve, reject) => {
    // 检查浏览器支持
    const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition
    if (!SpeechRecognition) {
      throw new Error('当前浏览器不支持语音识别功能')
    }
    
    offlineText.value = '正在使用Web Speech API进行识别...'
    
    // 创建语音识别实例
    const recognition = new SpeechRecognition()
    recognition.continuous = true
    recognition.interimResults = true
    recognition.lang = 'zh-CN'
    recognition.maxAlternatives = 1
    
    let recognizedText = ''
    let isCompleted = false
    
    const cleanup = () => {
      if (!isCompleted) {
        isCompleted = true
        isProcessing.value = false
      }
    }
    
    recognition.onresult = (event) => {
      for (let i = event.resultIndex; i < event.results.length; i++) {
        if (event.results[i].isFinal) {
          recognizedText += event.results[i][0].transcript
        } else {
          // 显示临时结果
          offlineText.value = `正在识别: ${event.results[i][0].transcript}...`
        }
      }
    }
    
    recognition.onend = () => {
      offlineText.value = recognizedText || '未能识别出语音内容，请确保录音清晰且包含语音'
      cleanup()
      ElMessage.success('语音识别完成')
      resolve()
    }
    
    recognition.onerror = (event) => {
      console.error('Web Speech API识别错误:', event.error)
      
      cleanup()
      
      // 显示错误信息和录音详情
      const duration = recordingTime.value || 0
      offlineText.value = `语音识别失败: ${event.error}

录音信息：
- 录音时长：${Math.floor(duration / 60)}分${Math.floor(duration % 60)}秒
- 文件大小：${formatFileSize(audioSize.value)}
- 录音时间：${new Date().toLocaleString()}

建议：
1. 检查网络连接
2. 确保录音清晰，环境安静
3. 可以下载录音文件，稍后重试识别
4. 或者尝试使用在线语音识别功能`
      
      offlineErrorMessage.value = `语音识别失败: ${event.error}`
      ElMessage.error('语音识别失败')
      reject(new Error(event.error))
    }
    
    // 开始语音识别
    try {
      recognition.start()
      
      // 设置超时
      setTimeout(() => {
        try {
          recognition.stop()
        } catch (e) {
          // 忽略停止时的错误
        }
      }, duration * 1000 + 10000) // 音频时长 + 10秒缓冲
      
    } catch (error: any) {
      cleanup()
      reject(error)
    }
  })
}



// 文件处理相关方法
const handleFileChange = (file: any) => {
  const rawFile = file.raw
  if (!rawFile) return
  
  // 检查文件类型
  const allowedTypes = [
    'audio/mp3', 'audio/mpeg', 'audio/wav', 'audio/wave',
    'audio/m4a', 'audio/aac', 'audio/ogg', 'audio/webm', 'audio/flac'
  ]
  
  if (!allowedTypes.includes(rawFile.type) && !rawFile.name.match(/\.(mp3|wav|m4a|aac|ogg|webm|flac)$/i)) {
    ElMessage.error('不支持的文件格式，请上传音频文件')
    return
  }
  
  // 检查文件大小 (50MB限制)
  const maxSize = 50 * 1024 * 1024
  if (rawFile.size > maxSize) {
    ElMessage.error('文件大小不能超过50MB')
    return
  }
  
  selectedFile.value = rawFile
  fileErrorMessage.value = ''
  fileText.value = ''
  ElMessage.success(`文件 "${rawFile.name}" 上传成功`)
}

const beforeFileUpload = (_file: File) => {
  return false // 阻止自动上传
}

const handleExceed = () => {
  ElMessage.warning('只能上传一个文件，请先清除当前文件')
}

const clearFile = () => {
  selectedFile.value = null
  fileText.value = ''
  fileErrorMessage.value = ''
  processingProgress.value = 0
  processingStatus.value = ''
  if (fileUploadRef.value) {
    fileUploadRef.value.clearFiles()
  }
  ElMessage.info('已清除文件')
}

const processAudioFile = async () => {
  if (!selectedFile.value) {
    ElMessage.error('请先选择音频文件')
    return
  }
  
  fileProcessing.value = true
  fileErrorMessage.value = ''
  processingProgress.value = 0
  processingStatus.value = '正在准备处理...'
  
  try {
    // 模拟处理过程
    processingStatus.value = '正在读取音频文件...'
    processingProgress.value = 20
    
    await new Promise(resolve => setTimeout(resolve, 1000))
    
    processingStatus.value = '正在分析音频内容...'
    processingProgress.value = 40
    
    await new Promise(resolve => setTimeout(resolve, 1500))
    
    processingStatus.value = '正在进行语音识别...'
    processingProgress.value = 60
    
    // 这里应该调用实际的语音识别API
    // 由于是演示，我们使用模拟数据
    await new Promise(resolve => setTimeout(resolve, 2000))
    
    processingStatus.value = '正在处理识别结果...'
    processingProgress.value = 80
    
    await new Promise(resolve => setTimeout(resolve, 1000))
    
    // 模拟识别结果
    fileText.value = `这是从音频文件 "${selectedFile.value.name}" 中识别出的文本内容。

文件信息：
- 文件名：${selectedFile.value.name}
- 文件大小：${formatFileSize(selectedFile.value.size)}
- 文件类型：${selectedFile.value.type || '未知'}
- 处理时间：${new Date().toLocaleString()}

注意：这是一个演示结果。在实际应用中，这里会显示真实的语音识别结果。

语音识别技术可以将音频文件中的语音内容转换为文本，支持多种音频格式和语言。识别准确度取决于音频质量、说话清晰度、背景噪音等因素。`
    
    processingStatus.value = '处理完成'
    processingProgress.value = 100
    
    ElMessage.success('音频文件转换完成')
    
  } catch (error: any) {
    console.error('处理音频文件失败:', error)
    fileErrorMessage.value = `处理失败: ${error.message}`
    ElMessage.error('音频文件处理失败')
  } finally {
    fileProcessing.value = false
  }
}

const copyFileText = async () => {
  try {
    await navigator.clipboard.writeText(fileText.value)
    ElMessage.success('文本已复制到剪贴板')
  } catch (error) {
    ElMessage.error('复制失败')
  }
}

const downloadFileText = () => {
  const blob = new Blob([fileText.value], { type: 'text/plain' })
  const url = URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = `语音识别结果_${new Date().toISOString().slice(0, 19).replace(/:/g, '-')}.txt`
  document.body.appendChild(a)
  a.click()
  document.body.removeChild(a)
  URL.revokeObjectURL(url)
  ElMessage.success('文本已下载')
}

// 模式切换处理
const onModeChange = async (mode: 'online' | 'offline' | 'file') => {
  if (isRecording.value || fileProcessing.value) {
    ElMessage.warning('请先停止当前操作')
    recognitionMode.value = (isRecording.value || fileProcessing.value) ? 'online' : mode
    return
  }
  
  if (mode === 'offline') {
    ElMessage.info('已切换到离线录音模式，正在检查支持...')
    await checkOfflineSupport()
    if (isOfflineSupported.value) {
      ElMessage.success('离线录音功能已就绪，无需网络连接')
    }
  } else if (mode === 'file') {
    ElMessage.info('已切换到文件转文字模式')
  } else {
    ElMessage.info('已切换到在线语音识别模式')
  }
}

onMounted(async () => {
  initSpeechRecognition()
  
  // 初始化网络状态
  isOnline.value = networkManager.getOnlineStatus()
  
  // 监听网络状态变化
  networkManager.addListener(updateNetworkStatus)
  
  // 检查离线录音支持
  await checkOfflineSupport()
})

// 组件卸载时清理
onUnmounted(() => {
  if (recognition.value && isRecording.value) {
    recognition.value.stop()
  }
  
  // 清理离线录音资源
  if (offlineRecordingTimer) {
    clearInterval(offlineRecordingTimer)
  }
  if (offlineRecorder) {
    offlineRecorder.destroy()
  }
  if (offlineMediaStream) {
    offlineMediaStream.getTracks().forEach(track => track.stop())
  }
  
  // 停止网络监控
  stopNetworkMonitoring()
  
  // 清理所有定时器
  SafeTimer.clearAll()
  
  // 移除网络状态监听器
  networkManager.removeListener(updateNetworkStatus)
})
</script>

<style scoped>
.speech-container {
  max-width: 1000px;
  margin: 0 auto;
}

.mode-selector {
  margin-bottom: 20px;
  text-align: center;
}

.mode-selector .el-radio-group {
  display: flex;
  justify-content: center;
  gap: 10px;
}

/* 识别设置样式 */
.recognition-settings {
  margin-bottom: 20px;
  padding: 15px;
  background-color: #f8f9fa;
  border-radius: 8px;
  border: 1px solid #e9ecef;
}

.recognition-settings .el-form-item {
  margin-bottom: 0;
}

.recognition-settings .el-form-item__label {
  font-weight: 500;
  color: #495057;
}

/* 文件上传样式 */
.upload-section {
  margin-bottom: 20px;
}

.file-uploader {
  width: 100%;
}

.file-uploader .el-upload-dragger {
  width: 100%;
  height: 200px;
  border: 2px dashed #d9d9d9;
  border-radius: 8px;
  background: #fafafa;
  transition: all 0.3s ease;
}

.file-uploader .el-upload-dragger:hover {
  border-color: #409EFF;
  background: #f0f9ff;
}

.file-info {
  margin-bottom: 20px;
}

.file-details {
  padding: 15px;
}

.file-detail-item {
  display: flex;
  margin-bottom: 8px;
}

.file-detail-item .label {
  font-weight: 500;
  color: #606266;
  min-width: 80px;
}

.file-detail-item .value {
  color: #303133;
  flex: 1;
}

.progress-section {
  margin: 20px 0;
  text-align: center;
}

.progress-text {
  margin-top: 10px;
  color: #606266;
  font-size: 14px;
}

.speech-card {
  margin-bottom: 20px;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.card-header h2 {
  margin: 0;
  color: #333;
}

.speech-content {
  padding: 20px 0;
}

.control-section {
  text-align: center;
  margin-bottom: 30px;
}

.control-section .el-button {
  margin: 0 10px;
}

.status-section {
  margin-bottom: 30px;
}

.network-status {
  margin-bottom: 15px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}

.network-warning {
  color: #e6a23c;
  font-size: 12px;
  display: flex;
  align-items: center;
  gap: 4px;
}

.recording-network-status {
  color: #409eff;
  font-size: 12px;
  display: flex;
  align-items: center;
  gap: 4px;
  margin-top: 5px;
}

.network-monitor-icon {
  animation: pulse 2s infinite;
}

@keyframes pulse {
  0% { opacity: 1; }
  50% { opacity: 0.5; }
  100% { opacity: 1; }
}

.error-content {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.error-content p {
  margin: 0;
}

.error-actions {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
}

.network-help {
  padding: 20px 0;
}

.network-help h4 {
  color: #333;
  margin-bottom: 15px;
}

.network-help ol, .network-help ul {
  margin: 10px 0;
  padding-left: 20px;
}

.network-help li {
  margin: 8px 0;
  line-height: 1.6;
}

.text-section h3 {
  color: #333;
  margin-bottom: 15px;
}

.result-textarea {
  margin-bottom: 20px;
}

.action-section {
  text-align: center;
}

.action-section .el-button {
  margin: 0 10px;
}

.help-card {
  margin-top: 20px;
}

.help-list {
  padding-left: 20px;
}

.help-list li {
  margin-bottom: 8px;
  color: #666;
  line-height: 1.6;
}
</style>
